/*
	Normals calculation shader.
*/

//-----------------------------------------------------------------------------
[VERTEX]

void main()
{
}


//-----------------------------------------------------------------------------
[GEOMETRY]

layout(points) in;
layout(triangle_strip, max_vertices = 4) out;

out vec2	vTexcoord;

void main()
{
	gl_Position = vec4( -1.0, -1.0, 0.0, 1.0 );
	vTexcoord	= vec2( 0.0, 0.0 );
	EmitVertex();
	
	gl_Position = vec4( -1.0,  1.0, 0.0, 1.0 );
	vTexcoord	= vec2( 0.0, 1.0 );
	EmitVertex();
	
	gl_Position = vec4(  1.0, -1.0, 0.0, 1.0 );
	vTexcoord	= vec2( 1.0, 0.0 );
	EmitVertex();
	
	gl_Position = vec4(  1.0,  1.0, 0.0, 1.0 );
	vTexcoord	= vec2( 1.0, 1.0 );
	EmitVertex();
	
	EndPrimitive();
}


//-----------------------------------------------------------------------------
[FRAGMENT]

out vec4 outNormal;

uniform sampler2D	unHeightMap;
uniform float		unHeightScale;

in vec2	vTexcoord;


void CalcNormal(in vec3 v0, in vec2 tc0, in vec2 tc2, in vec2 tc1, in vec2 tex_size, inout vec3 normal)
{
	vec3	v1;
	vec3	v2;
	
	v1.xy = tc0 + tex_size * tc1;
	v1.z  = texture( unHeightMap, v1.xy ).r * unHeightScale;
	
	v2.xy = tc0 + tex_size * tc2;
	v2.z = texture( unHeightMap, v2.xy ).r * unHeightScale;
	
	normal += normalize( cross( v1 - v0, v2 - v0 ) );
}

vec3 SmoothNormal(in vec2 tc)
{
	vec2	tex_size = vec2(1.0) / textureSize( unHeightMap, 0 );
	float	center	 = texture( unHeightMap, tc ).r;
	vec3	v0		 = vec3( tc, center * unHeightScale );
	vec3	normal	 = vec3(0.0);
	
	CalcNormal( v0, tc, vec2( 0.0,  1.0), vec2( 1.0,  1.0), tex_size, normal );
	CalcNormal( v0, tc, vec2( 1.0,  0.0), vec2( 1.0, -1.0), tex_size, normal );
	CalcNormal( v0, tc, vec2( 0.0, -1.0), vec2(-1.0, -1.0), tex_size, normal );
	CalcNormal( v0, tc, vec2(-1.0,  0.0), vec2(-1.0,  1.0), tex_size, normal );
	
	return normalize( normal );
}

void main()
{
	outNormal = vec4( SmoothNormal( vTexcoord ), 0.0 );
}

